# encoding:utf-8
'''
@author : xaing
@time : 2019/4/5 23:14
@地址 : 广州
@作用 : 数据库相关
@结果 :
'''



'''SQLite数据库是一款非常小巧的嵌入式开源数据库软件，也就是说
没有独立的维护进程，所有的维护都来自于程序本身。
在python中，使用sqlite3创建数据库的连接，当我们指定的数据库文件不存在的时候
连接对象会自动创建数据库文件；如果数据库文件已经存在，则连接对象不会再创建
数据库文件，而是直接打开该数据库文件。
    连接对象可以是硬盘上面的数据库文件，也可以是建立在内存中的，在内存中的数据库
    执行完任何操作后，都不需要提交事务的(commit)

    创建在硬盘上面： conn = sqlite3.connect('c:\\test\\test.db')
    创建在内存上面： conn = sqlite3.connect('"memory:')

    下面我们一硬盘上面创建数据库文件为例来具体说明：
    conn = sqlite3.connect('c:\\test\\hongten.db')
    其中conn对象是数据库链接对象，而对于数据库链接对象来说，具有以下操作：

        commit()            --事务提交
        rollback()          --事务回滚
        close()             --关闭一个数据库链接
        cursor()            --创建一个游标

    cu = conn.cursor()
    这样我们就创建了一个游标对象：cu
    在sqlite3中，所有sql语句的执行都要在游标对象的参与下完成
    对于游标对象cu，具有以下具体操作：

        execute()           --执行一条sql语句
        executemany()       --执行多条sql语句
        close()             --游标关闭
        fetchone()          --从结果中取出一条记录
        fetchmany()         --从结果中取出多条记录
        fetchall()          --从结果中取出所有记录
        scroll()            --游标滚动

'''

import sqlite3
import uuid

from version1 import common
from version1 import logUtils as log





def getUUID():
    '''
    返回一个UUID
    :return:
    '''
    return uuid.uuid1()


def getConnectSqlite3(path):
    '''
    获取一个sqlite的数据库连接。如果数据库不存在，则创建
    :param path: 数据库的路径， e:/temp/data.db
    :return:
    '''
    if common.checkNull(path):
        raise Exception("文件路径不能为空")

    conn = sqlite3.connect(path)
    return conn


def execute(connect, sql, commit):
    '''
    执行sql，并返回结果。注意，这是简单的sql执行方法，会存在sql注入的可能
    :param connect: 数据库连接
    :param sql: sql语句
    :param commit: 是否提交事务，true 提交事务 false 不自动提交事务
    :return: 如果非查询语句，返回影响的行数，查询语句返回结果集
    '''
    if connect is None:
        raise Exception("数据库连接断开，请重新连接")

    if common.checkNull(sql):
        raise Exception("sql不能为空")

    cursor = None
    cursor = connect.cursor()
    try:
        # 转换为小写
        sql = sql.lower()

        if sql.find('create') != -1:
            connect.execute(str(sql))
            log.outInfoLog("执行sql: ", sql)
            log.outInfoLog("SQL影响的行数:", cursor.rowcount, " 行")
            return cursor.rowcount

        elif sql.find('update') != -1:
            return cursor.rowcount

        elif sql.find('select') != -1:
            # 创建一个Cursor(游标)
            cursor.execute(str(sql))
            log.outInfoLog("执行sql: ", sql)
            log.outInfoLog("SQL影响的行数:", cursor.rowcount, " 行")
            # 获得查询结果集， 结果集是一个list，每个元素都是一个tuple，对应一行记录
            result = cursor.fetchall()
            log.outDebugLog(result)
            return result

        elif sql.find('delete') != -1:
            connect.execute(str(sql))
            log.outInfoLog("执行sql: ", sql)
            return cursor.rowcount

        elif sql.find('insert') != -1:
            connect.execute(str(sql))
            log.outInfoLog("执行sql: ", sql)
            log.outInfoLog("SQL影响的行数:", cursor.rowcount, " 行")
            return cursor.rowcount

        elif sql.find('drop') != -1:
            connect.execute(str(sql))
            log.outInfoLog("执行sql: ", sql)
            log.outInfoLog("SQL影响的行数:", cursor.rowcount, " 行")
            return cursor.rowcount

    except Exception as e:
        log.outErrorLog("执行sql错误，错误信息：", e)
    finally:
        if cursor is not None:
            # 关闭Cursor
            cursor.close()

        if commit:
            # 提交事务
            connect.commit()


def existTable(tableName, connect):
    '''
    sqlite 判断表是否存在，
    :param tableName: 表名
    :param connect: 数据库连接
    :return: true 表存在 false 表不存在
    '''
    if common.checkNull(tableName):
        raise Exception("表名不能为空")

    if connect is None:
        raise Exception("数据库连接断开，请重新连接")

    sql = "SELECT COUNT(*) FROM sqlite_master where type='table' and name='" + str(tableName) + "'"
    result = execute(connect, sql, False)
    if result[0][0] == 0:
        return False
    elif result[0][0] == 1:
        return True



def executeParm(connect, sql, commit, parm):
    '''
    执行sql，并返回结果。注意，这是简单的sql执行方法，会存在sql注入的可能
    :param connect: 数据库连接
    :param sql: sql语句 insert into people values (?, ?)
    :param parm: 参数,sql语句中的参数 如：(1,2,"4",4)
    :param commit: 是否提交事务，true 提交事务 false 不自动提交事务
    :return: 如果非查询语句，返回影响的行数，查询语句返回结果集
    '''
    if connect is None:
        raise Exception("数据库连接断开，请重新连接")

    if common.checkNull(sql):
        raise Exception("sql不能为空")

    cursor = None
    try:
        # 创建一个Cursor(游标)
        cursor = connect.cursor()
        if parm is None:
            cursor.execute(str(sql))
        else:
            cursor.execute(str(sql), parm)

        log.outInfoLog("执行sql: ", sql)
        log.outInfoLog("SQL影响的行数:", cursor.rowcount, " 行")

        # 转换为小写
        sql = sql.lower()

        if sql.find('create') != -1:
            return cursor.rowcount

        elif sql.find('update') != -1:
            return cursor.rowcount

        elif sql.find('select') != -1:
            # 获得查询结果集， 结果集是一个list，每个元素都是一个tuple，对应一行记录
            return cursor.fetchall()

        elif sql.find('delete') != -1:
            return cursor.rowcount

        elif sql.find('insert') != -1:
            return cursor.rowcount

        elif sql.find('drop') != -1:
            return cursor.rowcount
    finally:
        if cursor is not None:
            # 关闭Cursor
            cursor.close()

        if commit:
            # 提交事务
            connect.commit()


def forSelect(result):
    '''
    对查询结果进行遍历
    :param result: 查询的结果集
    :return: 无返回
    '''
    if len(result) > 0:
        for e in range(len(result)):
            print(result[e])


def commit(connect):
    '''
    事务提交
    :param connect: 数据库连接
    :return:
    '''
    connect.commit()


def colse(connect):
    '''
    关闭数据库连接，最后一定要指定的操作
    :param connect: 数据库连接
    :return:
    '''
    connect.close()


